package simpledb.planner;

import simpledb.tx.Transaction;
import simpledb.query.*;
import simpledb.parse.*;
import simpledb.server.SimpleDB;
import java.util.*;
import java.io.*;



/**
 * The simplest, most naive query planner possible.
 * @author Edward Sciore
 */
public class BasicQueryPlanner implements QueryPlanner {
   
   /**
    * Creates a query plan as follows.  It first takes
    * the product of all tables and views; it then selects on the predicate;
    * and finally it projects on the field list. 
    */
   public Plan createPlan(QueryData data, Transaction tx) {
	   FileOutputStream fout = null;
	   FileOutputStream foutTree = null;
	   try {
		fout = new FileOutputStream ("lastQueryLog");
		foutTree = new FileOutputStream ("tree");
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}
      //Step 1: Create a plan for each mentioned table or view
      List<Plan> plans = new ArrayList<Plan>();
      new PrintStream(fout).println ("The table(s) are: " + data.tables());
      new PrintStream(foutTree).println (data.tables());
      for (String tblname : data.tables()) {
         String viewdef = SimpleDB.mdMgr().getViewDef(tblname, tx);
         if (viewdef != null)
            plans.add(SimpleDB.planner().createQueryPlan(viewdef, tx));
         else
         {
        	 TablePlan tablePlan = new TablePlan(tblname, tx);
        	 new PrintStream(fout).println("Created plan for Table: " + tblname + " with blocksAccessed: " + tablePlan.blocksAccessed());
        	 plans.add(tablePlan);
         }
      }

      //Step 2: Create the product of all table plans
      int totalTablePlansProductBlocksAccessed = 0;
      Plan p = plans.remove(0);
      for (Plan nextplan : plans)
      {
         p = new ProductPlan(p, nextplan);
         totalTablePlansProductBlocksAccessed += p.blocksAccessed();
      }
      if(totalTablePlansProductBlocksAccessed != 0)
      {
    	  new PrintStream(fout).println("Created product between all the table plans with blocksAccessed: " + totalTablePlansProductBlocksAccessed);
      }
      else
      {
    	  new PrintStream(fout).println("No product between tables, moving to next stage"); 
      }

      //Step 3: Add a selection plan for the predicate
      p = new SelectPlan(p, data.pred());
      if (data.pred().toString() == "")
      {
    	  new PrintStream(fout).println("The predicate list is empty");
      }
      else
      {
    	  new PrintStream(fout).println("Created a selection plan for the Predicate(s): " + data.pred() + " with blocksAccessed:" + p.blocksAccessed());
    	  new PrintStream(foutTree).println(data.pred());
      }
      new PrintStream(fout).println("The estimated number of output records is: " + p.recordsOutput());
      
      //Step 4: Project on the field names
      p = new ProjectPlan(p, data.fields());
      new PrintStream(fout).println("Created a plan for the field(s) projection: " + data.fields() + " with blocksAccessed: " + p.blocksAccessed());
      new PrintStream(foutTree).println(data.fields());


//      Collection<String> projectionList = data.fields();
//      Iterator projectionListIterator = projectionList.iterator();
//      while(projectionListIterator.hasNext())
//      {
//    	  System.out.println(projectionListIterator.next());
//      }
//      System.out.println("The fields are: " + projectionList.toString());
//      new PrintStream(fout).println ("hello world!");
      try {
		fout.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
      return p;
   }
}
